#ifndef DISK_MANAGER_H
#define DISK_MANAGER_H

#include "page.h"
#include"common.h"
#include <string>
#include <fstream>
#include <mutex>
#include <memory>

/**
 * @brief 磁盘管理器类
 * 负责数据库文件的物理存储管理，提供页级的磁盘I/O操作
 * 这是存储系统的最底层组件，直接与文件系统交互
 */
class DiskManager {
public:
    /**
     * @brief 构造函数
     * @param db_file_path 数据库数据文件路径（如："./data/mydatabase.db"）
     * @param meta_file_path 数据库元数据文件路径（如："./data/mydatabase.meta"）
     * @throw std::runtime_error 如果文件打开或初始化失败
     */
    DiskManager(const std::string& db_file_path, const std::string& meta_file_path);
    
    /**
     * @brief 析构函数
     * 自动关闭文件并确保资源清理
     */
    ~DiskManager();

    // 禁用拷贝和移动
    DiskManager(const DiskManager&) = delete;
    DiskManager& operator=(const DiskManager&) = delete;
    DiskManager(DiskManager&&) = delete;
    DiskManager& operator=(DiskManager&&) = delete;

    /**
     * @brief 分配一个新页
     * @return 新分配的页ID，失败返回INVALID_PAGE_ID
     * @note 线程安全
     */
    page_id_t allocate_page();

    /**
     * @brief 释放一个页
     * @param page_id 要释放的页ID
     * @return true如果成功，false如果失败（如页ID无效）
     * @note 线程安全
     */
    bool free_page(page_id_t page_id);

    /**
     * @brief 读取页内容到指定缓冲区
     * @param page_id 要读取的页ID
     * @param data 目标缓冲区，必须至少能容纳PAGE_SIZE字节
     * @return true如果成功，false如果失败（如页ID无效或I/O错误）
     * @note 线程安全，缓冲区由调用者分配和管理
     */
    bool read_page(page_id_t page_id, char* data);

    /**
     * @brief 将数据写入指定页
     * @param page_id 要写入的页ID
     * @param data 源数据，必须包含PAGE_SIZE字节的有效数据
     * @return true如果成功，false如果失败（如页ID无效或I/O错误）
     * @note 线程安全，会确保数据持久化到磁盘
     */
    bool write_page(page_id_t page_id, const char* data);


    /**
     * @brief 获取当前数据库的总页数量
     * @return 已分配的页总数
     * @note 线程安全
     */
    size_t get_page_count() const;

    /**
     * @brief 获取数据库文件大小（字节）
     * @return 数据库文件当前大小
     * @note 线程安全
     */
    size_t get_file_size() const;

    /**
     * @brief 强制将所有缓冲数据刷新到磁盘
     * @return true如果成功，false如果失败
     * @note 用于确保数据持久化，性能开销较大
     */
    bool flush();

    /**
     * @brief 检查页ID是否有效
     * @param page_id 要检查的页ID
     * @return true如果页ID有效且在范围内，false否则
     * @note 线程安全
     */
    bool is_valid_page_id(page_id_t page_id) const;

private:
    /**
     * @brief 初始化数据库文件
     * @return true如果成功，false如果失败
     * @note 在构造函数中自动调用
     */
    bool initialize_files();

    /**
     * @brief 从元数据文件加载元数据
     * @return true如果成功，false如果失败
     */
    bool load_metadata();

    /**
     * @brief 保存元数据到元数据文件
     * @return true如果成功，false如果失败
     */
    bool save_metadata();

    /**
     * @brief 扩展数据库文件大小
     * @param new_size 新的文件大小（字节）
     * @return true如果成功，false如果失败
     */
    bool extend_file(size_t new_size);

    /**
     * @brief 验证页ID范围
     * @param page_id 要验证的页ID
     * @return true如果页ID有效，false否则
     */
    bool validate_page_id(page_id_t page_id) const;

    /**
     * @brief 将数据写入指定页
     * @param page_id 要写入的页ID
     * @param data 源数据，必须包含PAGE_SIZE字节的有效数据
     * @return true如果成功，false如果失败（如页ID无效或I/O错误）
     * @note 没有互斥锁保护，调用者需确保线程安全，适用于嵌套锁问题
     */
    bool write_page_no_lock(page_id_t page_id, const char* data);

     /**
     * @brief 读取页内容到指定缓冲区
     * @param page_id 要读取的页ID
     * @param data 目标缓冲区，必须至少能容纳PAGE_SIZE字节
     * @return true如果成功，false如果失败（如页ID无效或I/O错误）
     * @note 没有互斥锁保护，调用者需确保线程安全，适用于嵌套锁问题
     */
    bool read_page_no_lock(page_id_t page_id, char* data);

    
    // 成员变量
    std::string db_file_path_;      // 数据库数据文件路径
    std::string meta_file_path_;    // 数据库元数据文件路径
    mutable std::mutex mutex_;      // 互斥锁用于线程安全
    
    std::fstream db_file_;          // 数据库数据文件流
    // std::fstream meta_file_;        // 元数据文件流
    
    page_id_t next_page_id_;        // 下一个可分配的页ID
    size_t page_count_;             // 当前总页数量
    size_t file_size_;              // 当前文件大小（字节）
    page_id_t free_list_head_;      // 空闲链表头，初始为 INVALID_PAGE_ID

    // 元数据相关（可根据需要扩展）
    // uint32_t checksum_;                 // 文件校验和
    // std::string version_;               // 数据库版本信息
};

#endif // DISK_MANAGER_H